import json
import re
import asyncio
import xml.etree.ElementTree as ET
from logger import logger_main
from wx_api import download_image, download_emoji, send_text_message
from msg_stash import ReceivedMessage, RoomMessageDetail, MSG_TYPE, push_received_message_stash, clear_room_message_stash, push_room_message_stash, get_room_message_stash, get_received_message_stash, get_nickname, withdraw_room_message
from msg_sender import push_task
from typing import Dict
from config import DELAY_SECONDS

# 房间任务字典
ROOM_TASK_MAP: Dict[str, asyncio.Task] = {}


async def handle_text(detail: ReceivedMessage) -> bool:
    logger_main.info(
        f"消息解析成功,来自 {detail.send_user_nickname} 的文本信息,内容为:{detail.content}")
    if detail.content.startswith("/i") or detail.content.startswith("/clear"):
        logger_main.info(f"忽略该文本消息,内容为:{detail.content}")
        return False  # 返回 False 表示不需要创建延迟任务
    if detail.content == "/c":
        clear_room_message_stash(detail.from_user_wx_id)
        await asyncio.to_thread(send_text_message, detail.from_user_wx_id, "历史消息已清理")
        logger_main.info(f"已清除 {detail.from_user_wx_id} 的消息记录。")
        return False
    if detail.content == "/resend":
        message_list = get_room_message_stash(detail.from_user_wx_id)
        if not message_list:
            await asyncio.to_thread(send_text_message, detail.from_user_wx_id, "没有历史消息可供重新发送。")
            logger_main.info(f"[{detail.from_user_wx_id}] 没有历史消息可供重新发送。")
            return False
        await asyncio.to_thread(send_text_message, detail.from_user_wx_id, f"正在重新发送历史记录中{len(message_list)}条消息,请稍等...")
        logger_main.info(f"正在重新发送历史记录中{len(message_list)}条消息")
        await push_task(detail.from_user_wx_id, message_list.copy())
        return False  # 返回 False,不创建延迟任务
    push_room_message_stash(detail.from_user_wx_id, RoomMessageDetail(
        role="user",
        message_id=detail.message_id,
        message_type=MSG_TYPE.TEXT.value,
        send_user_nickname=detail.send_user_nickname,
        content=detail.content,
        create_time=detail.create_time,
        update_time=detail.create_time,
    ))
    return True  # 返回 True,需要创建延迟任务


async def handle_image(detail: ReceivedMessage) -> bool:
    logger_main.info(f"消息解析成功，来自 {detail.send_user_nickname} 的图片信息")
    root = ET.fromstring(detail.content)
    img_element = root.find('img')
    if img_element is not None:
        aeskey = img_element.get('aeskey', '')
        cdnthumburl = img_element.get('cdnthumburl', '')
        logger_main.info(
            f"开始下载图片，aeskey: {aeskey}, cdnthumburl: {cdnthumburl}")
        image_base64 = await asyncio.to_thread(download_image, aeskey, cdnthumburl)
        if image_base64:
            logger_main.info("图片下载Base64成功")
            push_room_message_stash(detail.from_user_wx_id, RoomMessageDetail(
                role="user",
                message_id=detail.message_id,
                message_type=MSG_TYPE.IMAGE.value,
                send_user_nickname=detail.send_user_nickname,
                content=detail.content,
                create_time=detail.create_time,
                update_time=detail.create_time,
                image_base64=image_base64,
            ))
            return True
    logger_main.error("❌ 无法解析图片信息的XML内容")
    return False


async def handle_emoji(detail: ReceivedMessage) -> bool:
    logger_main.info(f"消息解析成功，来自 {detail.send_user_nickname} 的表情信息")
    root = ET.fromstring(detail.content)
    emoji_element = root.find('emoji')
    if emoji_element is not None:
        cdnurl = emoji_element.get('cdnurl', '')
        logger_main.info(f"开始下载表情，cdnurl: {cdnurl}")
        emoji_base64 = await asyncio.to_thread(download_emoji, cdnurl)
        if emoji_base64:
            logger_main.info("表情下载Base64成功")
            push_room_message_stash(detail.from_user_wx_id, RoomMessageDetail(
                role="user",
                message_id=detail.message_id,
                message_type=MSG_TYPE.EMOJI.value,
                send_user_nickname=detail.send_user_nickname,
                content=detail.content,
                create_time=detail.create_time,
                update_time=detail.create_time,
                emoji_base64=emoji_base64,
            ))
        return True
    logger_main.error("❌ 无法解析表情信息的XML内容")
    return False


async def handle_video(detail: ReceivedMessage):
    logger_main.info(f"消息解析成功，来自 {detail.send_user_nickname} 的视频信息")
    pass


async def handle_voice(detail: ReceivedMessage):
    logger_main.info("接收到语音信息")
    pass


async def handle_quote(detail: ReceivedMessage):
    logger_main.info("接收到引用信息")
    pass


async def handle_rubbish_message(detail: ReceivedMessage):
    logger_main.info("接收到垃圾信息")
    pass


async def handle_entry_chatroom(detail: ReceivedMessage):
    logger_main.info("接收到加入群聊信息")
    pass


async def handle_system_message(detail: ReceivedMessage):
    logger_main.info(f"消息解析成功，来自 {detail.send_user_nickname} 的系统消息")
    logger_main.info(f"系统消息内容: {detail}")
    if "邀请你加入了群聊" in detail.content:
        logger_main.info(f"处理邀请加入群聊的系统消息")
        # 解析出群聊信息
        root = ET.fromstring(detail.content)
        inviter_nickname_element = root.find(
            './/link[@name="username"]/memberlist/member/nickname')
        others_nickname_element = root.find(
            './/link[@name="others"]/memberlist/member/nickname')
        inviter_nickname = inviter_nickname_element.text if inviter_nickname_element is not None else "未知用户"
        others_nickname = others_nickname_element.text if others_nickname_element is not None else "未知用户"
        await push_task(detail.from_user_wx_id, [RoomMessageDetail(
            role="user",
            message_id=detail.message_id,
            message_type=MSG_TYPE.INVITE.value,
            send_user_nickname=inviter_nickname if inviter_nickname is not None else "未知用户",
            content=f"{inviter_nickname}邀请你加入了群聊，群聊参与人还有：{others_nickname}",
            create_time=detail.create_time,
            update_time=detail.create_time,
        )])
        return False
    elif "拍了拍我" in detail.content:
        logger_main.info(f"处理拍一拍的系统消息")
        root = ET.fromstring(detail.content)
        template_element = root.find('.//template')
        if template_element is None:
            logger_main.error("❌ 无法解析拍一拍系统消息的XML内容")
            return
        template_text = template_element.text if template_element.text is not None else ""
        pattern = r'\$\{(.+?)\}'
        wxids = re.findall(pattern, template_text)
        for wxid in wxids:
            template_text = template_text.replace(
                f"${{{wxid}}}", f"{get_nickname(wxid)}")
        template_text.replace("拍了拍我", "拍了拍你")
        logger_main.info(f"处理后的拍一拍模板文本: {template_text}")
        push_room_message_stash(detail.from_user_wx_id, RoomMessageDetail(
            role="user",
            message_id=detail.message_id,
            message_type=MSG_TYPE.PAT.value,
            send_user_nickname=detail.send_user_nickname,
            content=template_text,
            create_time=detail.create_time,
            update_time=detail.create_time,
        ))
        return True
    elif "撤回了一条消息" in detail.content:
        logger_main.info(f"处理撤回消息的系统消息")
        # 解析出撤回的消息ID
        root = ET.fromstring(detail.content)
        msgid_element = root.find('.//newmsgid')
        if msgid_element is None:
            logger_main.error("❌ 无法解析撤回消息的XML内容")
            return
        msgid = msgid_element.text if msgid_element.text is not None else "0"
        msgid = int(msgid)
        logger_main.info(f"撤回的消息ID: {msgid}")
        # 从已接收消息缓存中查找对应的消息
        received_message = get_received_message_stash(msgid)
        if received_message is None:
            logger_main.error(f"❌ 未找到对应的已接收消息，消息ID: {msgid}")
            return
        withdraw_room_message(detail.from_user_wx_id,
                              msgid, detail.create_time)
        return True


async def process_batch_after_delay(FromUserName: str):
    try:
        logger_main.info(f"[{FromUserName}] 开始 {DELAY_SECONDS} 秒等待...")
        await asyncio.sleep(DELAY_SECONDS)

    except asyncio.CancelledError:
        logger_main.info(f"[{FromUserName}] 计时器被重置。等待用户发送消息！")
        return

    message_list = get_room_message_stash(FromUserName)
    if not message_list:
        logger_main.info(f"[{FromUserName}] 没有待处理的消息。")
        return

    logger_main.info(
        f"[{FromUserName}] {DELAY_SECONDS}秒等待成功，添加 {len(message_list)} 条消息至任务队列!")

    await push_task(FromUserName, message_list.copy())

    if FromUserName in ROOM_TASK_MAP:
        del ROOM_TASK_MAP[FromUserName]

MSG_DICT = {
    1: handle_text,  # 文本信息
    3: handle_image,  # 图片信息
    34: handle_voice,  # 语音信息
    43: handle_video,  # 视频信息
    47: handle_emoji,  # 表情信息
    49: handle_quote,  # 引用信息
    51: handle_rubbish_message,  # 垃圾信息
    10000: handle_entry_chatroom,  # 加入群聊信息(自己加入群聊)
    10002: handle_system_message,  # 系统消息(撤回，拍一拍信息，被邀请加入群聊)
}


async def handle_message(message):
    message_detail: ReceivedMessage | None = push_received_message_stash(
        message)
    if message_detail is None:
        return
    handler = MSG_DICT.get(message_detail.message_type, None)
    if handler:
        logger_main.debug(f"解析消息体: {json.dumps(message, ensure_ascii=False)}")
        if message_detail.from_user_wx_id in ROOM_TASK_MAP:
            ROOM_TASK_MAP[message_detail.from_user_wx_id].cancel()
            del ROOM_TASK_MAP[message_detail.from_user_wx_id]
        try:
            should_create_task = await handler(message_detail)
            # 只有当 handler 返回 True 时才创建延迟任务
            if should_create_task is not False:  # 默认为 True(兼容其他 handler)
                new_task = asyncio.create_task(
                    process_batch_after_delay(message_detail.from_user_wx_id)
                )
                ROOM_TASK_MAP[message_detail.from_user_wx_id] = new_task
        except Exception as e:
            logger_main.error(
                f"❌ 处理消息时出错: {e}，消息内容:\n{json.dumps(message, ensure_ascii=False, indent=4)}")
            return
    else:
        logger_main.error(
            f"❌ 未处理的消息类型: {message_detail.message_type}，消息内容:\n{json.dumps(message, ensure_ascii=False, indent=4)}")
